package com.sanq.product.mcgs.filter;

import com.sanq.product.config.utils.annotation.LogAnnotation;
import com.sanq.product.config.utils.web.GlobalUtil;
import com.sanq.product.config.utils.web.JsonUtil;
import com.sanq.product.mcgs.entity.vo.LogsVo;
import com.sanq.product.mcgs.entity.vo.MemberVo;
import com.sanq.product.mcgs.service.LogsService;
import com.sanq.product.mcgs.util.RequestUtil;
import com.sanq.product.security.utils.ParamUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;

public class LogsFilter implements HandlerInterceptor {

    @Resource
    private ThreadPoolTaskExecutor taskExecutor;
    @Resource
    private LogsService logsService;

    private static final ThreadLocal<LogsVo> LOGS_VO_THREAD_LOCAL = new ThreadLocal<LogsVo>();

    private static final ThreadLocal<Date> DATE_THREAD_LOCAL = new ThreadLocal<>();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse httpServletResponse, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod hm = (HandlerMethod) handler;
            LogAnnotation logAnnotation = (LogAnnotation) hm.getMethodAnnotation(LogAnnotation.class);

            if (logAnnotation != null) {
                Date begin = new Date();
                DATE_THREAD_LOCAL.set(begin);
                LogsVo logsVo = new LogsVo();

                logsVo.setMethod(request.getMethod());
                logsVo.setOperateDate(begin);
                logsVo.setRemoteAddr(GlobalUtil.getIpAddr(request));
                logsVo.setRequestUri(request.getRequestURI().replace(request.getContextPath(), ""));

                if (request.getMethod().equalsIgnoreCase("get")) {
                    logsVo.setParams(JsonUtil.obj2Json(ParamUtils.getInstance().getParam2Get(request)));
                } else {
                    logsVo.setParams(ParamUtils.getInstance().get());
                }

                logsVo.setTitle(logAnnotation.description());

                MemberVo memberVo = RequestUtil.get();

                if (memberVo != null) {
                    logsVo.setUserId(memberVo.getId());
                    logsVo.setLoginName(memberVo.getLoginName());
                }
                LOGS_VO_THREAD_LOCAL.set(logsVo);
            }
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, ModelAndView modelAndView) throws Exception {
        LogsVo logsVo = LOGS_VO_THREAD_LOCAL.get();

        if (logsVo != null) {
            long begin = DATE_THREAD_LOCAL.get().getTime();
            long end = System.currentTimeMillis();

            logsVo.setTimeout((end - begin) + "ms");

            taskExecutor.execute(() -> logsService.save(logsVo));
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, Exception e) throws Exception {
        LOGS_VO_THREAD_LOCAL.remove();
        DATE_THREAD_LOCAL.remove();
    }
}
